package com.woniuxy.threadmethods;

import com.woniuxy.untis.Sleep;
import lombok.*;
import lombok.extern.slf4j.Slf4j;

import java.util.LinkedList;

/**
 * <P> @Author: ideaAdmin
 * <P> TODO: Class
 * <P> TODO: 线程间的消息队列
 * <P> Date: 2022/4/7:17:40
 * <P> Description:
 */
@Slf4j(topic = "c.Test22")
public class Test22 {
    public static void main(String[] args) {
        MessageQueue messageQueue = new MessageQueue(2);

        for (int i = 0; i < 3; i++) {
            int id = i;
            new Thread(() -> {
                messageQueue.put(new Message(id, "值" + id));
            }, "生产者" + i).start();
        }
        new Thread(() -> {
            while (true) {
                Sleep.sleep(1000);
                Message take = messageQueue.take();
            }
        }, "消费者").start();
    }
}

@Slf4j(topic = "c.MessageQueue")
class MessageQueue {


    /**
     * TODO 消息队列的集合
     */
    private LinkedList<Message> list = new LinkedList<>();

    /**
     * TODO 队列容量
     */
    private int capacity;

    public MessageQueue(int capacity) {
        this.capacity = capacity;
    }

    /**
     * TODO:获取消息
     **/
    public Message take() {

        //TODO 队列是否为空

        synchronized (list) {
            while (list.isEmpty()) {
                try {
                    log.debug("队列为空，消费者等待");
                    list.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //返回头数据
            Message message = list.removeFirst();
            list.notifyAll();
            log.debug("消费者消费消息");
            return message;
        }
    }

    /**
     * TODO:存入消息
     **/
    public void put(Message message) {

        synchronized (list) {
            //检查队列是否已满
            while (list.size() == capacity) {
                try {
                    log.debug("队列满了，生产者等待");
                    list.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //将新的消息放到尾部
            list.addLast(message);
            list.notifyAll();
            log.debug("生产者生成消息");
        }

    }


}

@AllArgsConstructor
@NoArgsConstructor
@ToString
@EqualsAndHashCode
final class Message {
    private int id;
    private Object value;
}
